<?php

/**
 * SSO单点登录客户端
 * Yii用法示例：
 *      Yii::import('ext.SsoClient.*');
 *      Client::getInstance()->get_user('水平凡');
 * File Name：Client.php
 * File Encoding：UTF-8
 * File New Time：2014-10-21 13:28:03
 * Author：水平凡
 * Mailbox：admin@abc3210.com
 */
define('CLIENT_ROOT', substr(__FILE__, 0, -10));

class Client {

    //错误信息
    protected $error = NULL;
    //配置信息
    protected $config = array(
        'client_id' => 0, //站点id
        'client_key' => '', //站点密钥
        'key_validity' => 3000, //密文有效期，单位秒
    );
    //接口动作
    protected $action = NULL;
    //数据
    protected $data = array();
    //服务端地址
    protected $servicesUrl = 'http://www.1zw.com/sso/';
    //当前时间
    protected $time = 0;

    public function __construct($config = array()) {
        if (is_array($config) && !empty($config)) {
            $this->config = array_merge($this->config, $config);
        }
        if (isset($config['servicesUrl'])) {
            $this->servicesUrl = $config['servicesUrl'];
        }
        if (defined('YII_DEBUG') && YII_DEBUG && !isset($config['servicesUrl'])) {
            $this->servicesUrl = 'http://cs.1zw.com/sso/';
        }
        $this->time = time();
    }

    /**
     * 链接服务
     * @staticvar null $handier
     * @return \Client
     */
    static public function getInstance($config = array()) {
        static $handier = NULL;
        if (empty($handier)) {
            $handier = new self($config);
        }
        return $handier;
    }

    /**
     * 获取最近的一条错误信息
     * @return string
     */
    public function getError() {
        return $this->error;
    }

    /**
     * 用户注册
     * @param type $username 用户名
     * @param type $password 明文密码
     * @param type $email 电子邮件
     * @param type $phone 手机号，可以为空
     * @return int 成功返回uid，失败返回false
     */
    public function user_register($username, $password, $email, $phone = '') {
        $this->action = "user/register";
        if (empty($username)) {
            $this->error = '用户名不能为空！';
            return false;
        }
        if (empty($password)) {
            $this->error = '密码不能为空！';
            return false;
        }
        if (empty($email)) {
            $this->error = '邮箱不能为空！';
            return false;
        }
        $this->data = array(
            'username' => $username,
            'password' => $password,
            'email' => $email,
            'phone' => $phone,
        );
        $return = $this->send();
        if ($return['status']) {
            return $return['data'];
        }
        $this->error = $return['info'];
        return false;
    }

    /**
     * 用户登录验证
     * @param type $username 用户名 / 用户 ID / 用户邮箱
     * @param type $password 明文密码
     * @param type $type 登录方式：0用户名，1用户ID，2用户邮箱，默认0
     * @return array 成功返回用户基本信息数据，失败返回false
     */
    public function user_login($username, $password, $type = 0) {
        $this->action = "user/login";
        if (empty($username)) {
            $this->error = '用户名不能为空！';
            return false;
        }
        if (empty($password)) {
            $this->error = '密码不能为空！';
            return false;
        }
        $this->data = array(
            'username' => $username,
            'password' => $password,
            'type' => $type,
        );
        $return = $this->send();
        if ($return['status']) {
            return $return['data'];
        }
        $this->error = $return['info'];
        return false;
    }

    /**
     * 获取用户数据
     * @param type $username 用户名 / 用户 ID
     * @param type $isuid 是否使用uid获取，默认不是
     * @return array 成功返回用户基本信息数据，失败返回false
     */
    public function get_user($username, $isuid = 0) {
        $this->action = "user/getuser";
        if (empty($username)) {
            $this->error = $isuid ? '用户ID不能为空！' : '用户名不能为空！';
            return false;
        }
        $this->data = array(
            'username' => $username,
            'isuid' => $isuid,
        );
        $return = $this->send();
        if ($return['status']) {
            return $return['data'];
        }
        $this->error = $return['info'];
        return false;
    }

    /**
     *  更新用户资料
     * @param type $username 用户名
     * @param type $oldpw 旧密码
     * @param type $newpw 新密码，如不修改为空
     * @param type $email Email，如不修改为空
     * @param type $phone 手机号，如不修改为空
     * @param type $ignoreoldpw 是否忽略旧密码
     * @return boolean 成功返回true，失败返回false
     */
    public function user_edit($username, $data = array(), $newpw = '') {
        $this->action = "user/edit";
        if (empty($username)) {
            $this->error = '用户名不能为空！';
            return false;
        }
        $this->data = array(
            'username' => $username,
            'newpw' => $newpw,
        );
        unset($data['username'], $data['newpw'], $data['password']);
        $this->data = array_merge($this->data, $data);
        $return = $this->send();
        if ($return['status']) {
            return true;
        }
        $this->error = $return['info'];
        return false;
    }

    /**
     * 删除用户
     * @param type $username 用户名/用户UID
     * @param type $isuid 是否使用uid，默认用户名
     * @return boolean 成功返回true，失败返回false
     */
    public function user_delete($username, $isuid = 0) {
        $this->action = "user/delete";
        if (empty($username)) {
            $this->error = $isuid ? '用户ID不能为空！' : '用户名不能为空！';
            return false;
        }
        $this->data = array(
            'username' => $username,
            'isuid' => $isuid,
        );
        $return = $this->send();
        if ($return['status']) {
            return true;
        }
        $this->error = $return['info'];
        return false;
    }

    /**
     * 同步登录
     * @param type $uid 用户UID
     * @param type $isUrl 是否只返回url，默认返回script
     * @return string
     */
    public function user_synlogin($uid, $isUrl = false) {
        if (empty($uid)) {
            $this->error = '同步登录uid不能为空！';
            return false;
        }
        $apps = Fun::file('cache/apps');
        if (empty($apps)) {
            $apps = $this->getAppsList();
            //缓存
            Fun::file('cache/apps', $apps);
        }
        $synstr = '';
        $url = array();
        if (is_array($apps) && !empty($apps)) {
            foreach ($apps as $appid => $app) {
                if ($app['synlogin'] && $app['client_id'] != $this->config['client_id']) {
                    $url[$appid] = $app['url'] . '?time=' . $this->time . '&code=' . urlencode(Encrypt::authcode('action=synlogin&uid=' . $uid . '&time=' . $this->time, 'ENCODE', $app['client_key']));
                    $synstr .= '<script type="text/javascript" src="' . $url[$appid] . '"></script>';
                }
            }
        }
        return $isUrl ? $url : $synstr;
    }

    /**
     * 同步退出
     * @param type $isUrl 是否只返回url，默认返回script
     * @return boolean
     */
    public function user_synlogout($isUrl = false) {
        $apps = Fun::file('cache/apps');
        if (empty($apps)) {
            $apps = $this->getAppsList();
            //缓存
            Fun::file('cache/apps', $apps);
        }
        $synstr = '';
        $url = array();
        if (is_array($apps) && !empty($apps)) {
            foreach ($apps as $appid => $app) {
                if ($app['synlogin'] && $app['client_id'] != $this->config['client_id']) {
                    $url[$appid] = $app['url'] . '?time=' . $this->time . '&code=' . urlencode(Encrypt::authcode('action=synlogout&time=' . $this->time, 'ENCODE', $app['client_key']));
                    $synstr .= '<script type="text/javascript" src="' . $url[$appid] . '"></script>';
                }
            }
        }
        return $isUrl ? $url : $synstr;
    }

    /**
     * 获取Apps列表
     * @return array()
     */
    private function getAppsList() {
        $this->action = "apps/list";
        $return = $this->send();
        if ($return['status']) {
            return $return['data'];
        }
        $this->error = $return['info'];
        return false;
    }

    /**
     * 执行
     * @return boolean
     */
    private function send() {
        $curl = new Curl();
        if (!$curl->create()) {
            $this->error = 'SSO单点登录需要curl支持！';
            return false;
        }
        //parse_str就是将一个url ?后面的参数转换成一个数组
        $this->data['client_ip'] = Fun::get_client_ip();
        $data = array(
            'data' => Encrypt::authcode(http_build_query($this->data), 'ENCODE', $this->config['client_key'], $this->config['key_validity']),
            'client_id' => $this->config['client_id'],
        );
        if (empty($this->action)) {
            $this->action = 'index/index';
        }
        $return = $curl->post($this->servicesUrl . $this->action, $data);
        if ($return === false) {
            $this->error = '接口请求失败或超时！';
            return false;
        }
        $return = json_decode($return, true);
        if (empty($return)) {
            $this->error = '接口数据返回错误！';
            return false;
        }
        return $return;
    }

}
